package cc.flyflow.biz.service.impl;

import cc.flyflow.biz.api.ApiStrategyFactory;
import cc.flyflow.biz.org.entity.DeptUser;
import cc.flyflow.biz.org.entity.User;
import cc.flyflow.biz.org.entity.UserRole;
import cc.flyflow.biz.org.service.IDeptUserService;
import cc.flyflow.biz.org.service.IUserService;
import cc.flyflow.biz.process.entity.Process;
import cc.flyflow.biz.process.entity.*;
import cc.flyflow.biz.process.mapper.ProcessInstanceCopyMapper;
import cc.flyflow.biz.process.service.*;
import cc.flyflow.biz.service.ICombinationGroupService;
import cc.flyflow.biz.utils.CoreHttpUtil;
import cc.flyflow.biz.vo.FormGroupVo;
import cc.flyflow.biz.vo.ProcessDataQueryVO;
import cc.flyflow.biz.vo.ProcessInstanceCopyVo;
import cc.flyflow.biz.vo.ProcessInstanceRecordVO;
import cc.flyflow.common.base.BaseEntity;
import cc.flyflow.common.base.FlyflowBaseServiceImpl;
import cc.flyflow.common.constants.NodeUserTypeEnum;
import cc.flyflow.common.constants.ProcessInstanceConstant;
import cc.flyflow.common.constants.ProcessInstanceRecordStatusEnum;
import cc.flyflow.common.dto.PageDto;
import cc.flyflow.common.dto.PageResultDto;
import cc.flyflow.common.dto.R;
import cc.flyflow.common.dto.flow.FormItemVO;
import cc.flyflow.common.dto.flow.Node;
import cc.flyflow.common.dto.flow.node.parent.SuperUserRootNode;
import cc.flyflow.common.dto.process.ClearProcessParamDto;
import cc.flyflow.common.dto.process.TaskDto;
import cc.flyflow.common.dto.process.TaskQueryParamDto;
import cc.flyflow.common.dto.third.DeptDto;
import cc.flyflow.common.dto.third.UserDto;
import cc.flyflow.common.service.biz.IRemoteService;
import cc.flyflow.common.utils.DateUtil;
import cc.flyflow.common.utils.JsonUtil;
import cc.flyflow.common.utils.TenantUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 组合组服务
 *
 * @author Jyl
 */
@Service
@Slf4j
public class CombinationGroupServiceImpl extends FlyflowBaseServiceImpl implements ICombinationGroupService
{
    @Resource
    private IProcessGroupService processGroupService;

    @Resource
    private IUserService userService;

    @Resource
    private IDeptUserService deptUserService;

    @Resource
    private IProcessMainService processMainService;

    @Resource
    private IProcessService processService;

    @Resource
    private IProcessStarterService processStarterService;

    @Resource
    private IRemoteService remoteService;

    @Resource
    private IProcessInstanceRecordService processInstanceRecordService;

    @Resource
    private IProcessNodeDataService processNodeDataService;

    @Resource
    private IProcessInstanceCopyService processCopyService;
    @Autowired
    private ProcessInstanceCopyMapper processInstanceCopyMapper;

    /**
     * 根据部门id集合和角色id集合 获取用户列表
     *
     * @param deptIdList 部门id集合
     * @param roleIdList 角色key集合
     * @return
     */
    @Override
    public R<List<String>> queryUserListByDeptIdListAndRoleIdList(List<String> deptIdList, List<String> roleIdList)
    {
        MPJLambdaWrapper<User> wrapper = JoinWrappers.lambda(User.class).distinct().select(User::getId);

        if (CollUtil.isNotEmpty(deptIdList))
        {
            wrapper.innerJoin(DeptUser.class, DeptUser::getUserId, User::getId).in(DeptUser::getDeptId, deptIdList);
        }

        if (CollUtil.isNotEmpty(roleIdList))
        {
            wrapper.innerJoin(UserRole.class, UserRole::getUserId, User::getId).in(UserRole::getRoleId, roleIdList);
        }

        List<String> userIdList = userService.selectJoinList(String.class, wrapper);
        return R.success(userIdList);
    }

    /**
     * 查询表单组包含流程
     *
     * @param hidden
     * @return 表单组数据
     */
    @Override
    public R<List<FormGroupVo>> listGroupWithProcess(Boolean hidden)
    {
        List<FormGroupVo> formGroupVos = new LinkedList<>();

        List<ProcessGroup> processGroupList = processGroupService.lambdaQuery().
                eq(ProcessGroup::getTenantId, TenantUtil.get())
                .orderByDesc(ProcessGroup::getSort).list();

        processGroupList.forEach(group ->
        {
            FormGroupVo formGroupVo = FormGroupVo.builder()
                    .id((group.getId()))
                    .name(group.getGroupName())
                    .items(new LinkedList<>())
                    .build();
            formGroupVos.add(formGroupVo);

            List<Process> processList = processService.lambdaQuery()
                    .eq(Process::getGroupId, group.getId())
                    .eq(Process::getTenantId, TenantUtil.get())
                    .eq(hidden != null, Process::getHidden, hidden)
                    .eq(Process::getStop, false)
                    .orderByAsc(Process::getSort).orderByDesc(Process::getCreateTime).list();

            processList.forEach(process ->
            {
                formGroupVo.getItems().add(FormGroupVo.FlowVo.builder()
                        .flowId(process.getFlowId())
                        .rangeShow(process.getRangeShow())
                        .name(process.getName())
                        .logo(process.getLogo())
                        .remark(process.getRemark())
                        .stop(process.getStop())
                        .uniqueId(process.getUniqueId())
                        .updated(process.getUpdateTime())
                        .build());
            });
        });

        return R.success(formGroupVos);
    }

    /**
     * 查询流程组和主流程
     *
     * @return
     */
    @Override
    public R<List<FormGroupVo>> listGroupWithProcessMain()
    {
        List<FormGroupVo> formGroupVos = new LinkedList<>();

        //查询流程分组
        List<ProcessGroup> processGroupList = processGroupService.lambdaQuery()
                .eq(ProcessGroup::getTenantId, TenantUtil.get())
                .orderByDesc(ProcessGroup::getSort).list();

        processGroupList.forEach(group ->
        {
            FormGroupVo formGroupVo = FormGroupVo.builder()
                    .id((group.getId()))
                    .name(group.getGroupName())
                    .items(new LinkedList<>())
                    .build();
            formGroupVos.add(formGroupVo);

            //查询流程主函数
            List<ProcessMain> processMainList = processMainService.lambdaQuery()
                    .eq(ProcessMain::getTenantId, TenantUtil.get())
                    .eq(ProcessMain::getGroupId, group.getId())
                    .eq(ProcessMain::getTenantId, TenantUtil.get())
                    .orderByAsc(ProcessMain::getSort).orderByDesc(ProcessMain::getCreateTime).list();

            processMainList.forEach(processMain ->
            {
                //查询流程模版
                List<Process> processList = processService.lambdaQuery()
                        .eq(Process::getUniqueId, processMain.getUniqueId())
                        .eq(Process::getTenantId, TenantUtil.get())
                        .eq(Process::getHidden, false).orderByDesc(Process::getUpdateTime).list();

                Process process = null;
                {
                    process = processList.stream().filter(w -> !w.getStop()).findAny().orElse(null);
                    if (process == null)
                    {
                        process = processList.get(0);
                    }
                }

                Boolean reportEnable = false;

                formGroupVo.getItems().add(FormGroupVo.FlowVo.builder()
                        .flowId(process.getFlowId())
                        .uniqueId(process.getUniqueId())
                        .rangeShow(processMain.getRangeShow())
                        .name(processMain.getName())
                        .remark(process.getRemark())
                        .logo(processMain.getLogo())
                        .reportEnable(reportEnable)
                        .stop(process.getStop())
                        .uniqueId(processMain.getUniqueId())
                        .updated(processMain.getUpdateTime())
                        .build());
            });
        });
        return R.success(formGroupVos);
    }

    /**
     * 搜索流程
     *
     * @param word 关键词
     * @return
     */
    @Override
    public R<List<FormGroupVo.FlowVo>> searchFlowList(String word)
    {
        List<ProcessMain> processMainList = processMainService.lambdaQuery()
                .eq(ProcessMain::getTenantId, TenantUtil.get())
                .like(ProcessMain::getName, word)
                .orderByAsc(ProcessMain::getSort).orderByDesc(ProcessMain::getCreateTime).list();

        List<FormGroupVo.FlowVo> flowVoList = new ArrayList<>();

        for (ProcessMain processMain : processMainList)
        {
            List<Process> processList = processService.lambdaQuery()
                    .eq(Process::getUniqueId, processMain.getUniqueId())
                    .eq(Process::getTenantId, TenantUtil.get())
                    .eq(Process::getHidden, false).orderByDesc(Process::getUpdateTime).list();

            Process process = null;
            {
                process = processList.stream().filter(w -> !w.getStop()).findAny().orElse(null);
                if (process == null)
                {
                    process = processList.get(0);
                }
            }

            FormGroupVo.FlowVo flowVo = FormGroupVo.FlowVo.builder()
                    .flowId(process.getFlowId())
                    .uniqueId(process.getUniqueId())
                    .rangeShow(processMain.getRangeShow())
                    .name(processMain.getName())
                    .remark(process.getRemark())
                    .logo(processMain.getLogo())
                    .reportEnable(false)
                    .stop(process.getStop())
                    .uniqueId(processMain.getUniqueId())
                    .updated(processMain.getUpdateTime())
                    .build();

            flowVoList.add(flowVo);
        }

        return R.success(flowVoList);
    }

    /**
     * 查询所有我可以发起的表单组
     *
     * @return
     */
    @Override
    public R<List<FormGroupVo>> listCurrentUserStartGroup()
    {
        String userId = StpUtil.getLoginIdAsString();
        UserDto user = ApiStrategyFactory.getStrategy().getUser(userId);
        List<FormGroupVo> formGroupVos = new LinkedList<>();

        List<ProcessGroup> processGroupList = processGroupService.lambdaQuery()
                .eq(ProcessGroup::getTenantId, TenantUtil.get())
                .orderByDesc(ProcessGroup::getSort).list();

        processGroupList.forEach(group ->
        {
            FormGroupVo formGroupVo = FormGroupVo.builder()
                    .id((group.getId()))
                    .name(group.getGroupName())
                    .items(new LinkedList<>())
                    .build();
            formGroupVos.add(formGroupVo);

            List<Process> processList = processService.lambdaQuery()
                    .eq(Process::getTenantId, TenantUtil.get())
                    .eq(Process::getGroupId, group.getId())
                    .eq(Process::getHidden, false)
                    .eq(Process::getStop, false)
                    .orderByAsc(Process::getSort).list();

            Map<Long, Boolean> existMap = new HashMap<>();

            if (!processList.isEmpty())
            {
                List<Long> idList = processList.stream().map(w -> w.getId()).collect(Collectors.toList());
                //查询发起人集合
                List<ProcessStarter> processStarterList = processStarterService.lambdaQuery()
                        .eq(ProcessStarter::getTenantId, TenantUtil.get())
                        .in(ProcessStarter::getProcessId, idList).list();
                Map<Long, List<ProcessStarter>> groupmap =
                        processStarterList.stream().collect(Collectors.groupingBy(ProcessStarter::getProcessId));

                for (Process process : processList)
                {
                    List<ProcessStarter> processStarters = groupmap.get(process.getId());
                    if (processStarters == null)
                    {
                        existMap.put(process.getId(), true);
                        continue;
                    }
                    boolean match =
                            processStarters.stream().anyMatch(w -> w.getTypeId().equals(userId) && w.getType().equals(NodeUserTypeEnum.USER.getKey()));
                    if (match)
                    {
                        existMap.put(process.getId(), true);
                        continue;
                    }
                    Set<String> deptIdSet = new HashSet<>();

                    //需要查询包含子级的部门id
                    List<String> queryChildrenDeptIdList = new ArrayList<>();
                    for (ProcessStarter processStarter : processStarters)
                    {
                        if (processStarter.getType().equals(NodeUserTypeEnum.DEPT.getKey()))
                        {
                            deptIdSet.add(processStarter.getTypeId());
                            //包含下级
                            if (processStarter.getContainChildrenDept())
                            {
                                queryChildrenDeptIdList.add(processStarter.getTypeId());

                            }
                        }
                    }
                    Map<String, List<DeptDto>> childrenDeptMap =
                            remoteService.batchQueryChildDeptList(queryChildrenDeptIdList).getData();
                    for (Map.Entry<String, List<DeptDto>> entry : childrenDeptMap.entrySet())
                    {
                        Set<String> collect = entry.getValue().stream().map(DeptDto::getId).collect(Collectors.toSet());
                        deptIdSet.addAll(collect);
                    }

                    //判断部门交集
                    List<String> userDeptIdList = user.getDeptIdList();
                    existMap.put(process.getId(), !CollUtil.intersection(userDeptIdList, deptIdSet).isEmpty());
                }
            }

            processList.forEach(process ->
            {

                if (!existMap.get(process.getId()))
                {
                    return;
                }

                formGroupVo.getItems().add(FormGroupVo.FlowVo.builder()
                        .flowId(process.getFlowId())
                        .uniqueId(process.getUniqueId())
                        .name(process.getName())
                        .logo(process.getLogo())
                        .remark(process.getRemark())
                        .stop(process.getStop())
                        .updated(process.getUpdateTime())
                        .build());
            });
        });

        return R.success(formGroupVos);
    }

    /**
     * 删除主流程
     *
     * @param uniqueId
     * @return
     */
    @Transactional
    @Override
    public R deleteProcessMain(String uniqueId)
    {
        processMainService.lambdaUpdate()
                .eq(ProcessMain::getUniqueId, uniqueId)
                .eq(ProcessMain::getTenantId, TenantUtil.get())
                .remove();

        processService.lambdaUpdate().set(Process::getHidden, true)
                .eq(Process::getHidden, false)
                .eq(Process::getUniqueId, uniqueId)
                .eq(Process::getTenantId, TenantUtil.get())
                .update(new Process());

        return R.success();
    }

    /**
     * 清理所有流程
     *
     * @param uniqueId 流程唯一id
     * @return
     */
    @Transactional
    @Override
    public R clear(String uniqueId)
    {
        String tenantId = TenantUtil.get();
        List<Process> processList = processService.lambdaQuery()
                .eq(Process::getUniqueId, uniqueId)
                .eq(Process::getTenantId, tenantId)
                .list();

        if (CollUtil.isEmpty(processList))
        {
            return R.success();
        }

        List<String> flowIdList = processList.stream().map(Process::getFlowId).collect(Collectors.toList());
        List<Long> processIdList = processList.stream().map(BaseEntity::getId).collect(Collectors.toList());

        Map<String, IClearService> serviceMap = SpringUtil.getBeansOfType(IClearService.class);
        for (Map.Entry<String, IClearService> entry : serviceMap.entrySet())
        {
            entry.getValue().clearProcess(uniqueId, flowIdList, processIdList, tenantId);
        }

        String userId = StpUtil.getLoginIdAsString();
        UserDto userDto = ApiStrategyFactory.getStrategy().getUser(userId);

        //清理flowable
        ClearProcessParamDto clearProcessParamDto = new ClearProcessParamDto();
        clearProcessParamDto.setFlowIdList(flowIdList);
        clearProcessParamDto.setUserId(userId);
        clearProcessParamDto.setUserName(userDto.getName());

        R r = CoreHttpUtil.clearProcess(clearProcessParamDto);
        if (!r.isOk())
        {
            throw new RuntimeException("清理流程失败");
        }

        return R.success();
    }

    public void fn(String keyword)
    {
        ProcessInstanceRecord record = processInstanceRecordService.lambdaQuery()
                .eq(ProcessInstanceRecord::getProcessInstanceBizCode, keyword).one();
    }

    /**
     * 查询当前登录用户的待办任务
     *
     * @param pageVO
     * @return
     */
    @Override
    public R queryTodoTaskList(PageDto pageVO)
    {
        TaskQueryParamDto taskQueryParamDto = BeanUtil.copyProperties(pageVO, TaskQueryParamDto.class);

        //查询用户待办，没有用户id 用当前用户id
        if (StrUtil.isNotEmpty(pageVO.getAssignId()))
        {
            taskQueryParamDto.setAssign(pageVO.getAssignId());
        } else
        {
            taskQueryParamDto.setAssign(StpUtil.getLoginIdAsString());
        }

        R<PageResultDto<TaskDto>> r = CoreHttpUtil.queryTodoTask(taskQueryParamDto);

        PageResultDto<TaskDto> pageResultDto = r.getData();
        List<TaskDto> records = pageResultDto.getRecords();

        if (CollUtil.isEmpty(records))
        {
            return R.success(pageResultDto);
        }

        Set<String> processInstanceIdSet =
                records.stream().map(w -> w.getProcessInstanceId()).collect(Collectors.toSet());

        //流程实例记录
        List<ProcessInstanceRecord> processInstanceRecordList = processInstanceRecordService.lambdaQuery()
                .in(ProcessInstanceRecord::getProcessInstanceId, processInstanceIdSet)
                .in(ProcessInstanceRecord::getTenantId, TenantUtil.get())
                .list();

        //发起人
        Set<String> startUserIdSet =
                processInstanceRecordList.stream().map(w -> w.getUserId()).collect(Collectors.toSet());

        List<UserDto> startUserList = new ArrayList<>();
        {
            for (String userIds : startUserIdSet)
            {
                UserDto user = ApiStrategyFactory.getStrategy().getUser(userIds);
                startUserList.add(user);
            }
        }

        //流程配置
        Set<String> flowIdSet = processInstanceRecordList.stream().map(w -> w.getFlowId()).collect(Collectors.toSet());
        List<Process> processList = processService.lambdaQuery()
                .in(Process::getFlowId, flowIdSet)
                .eq(Process::getTenantId, TenantUtil.get())
                .list();

        for (TaskDto record : records)
        {
            ProcessInstanceRecord processInstanceRecord = processInstanceRecordList.stream().filter(w ->
                    StrUtil.equals(w.getProcessInstanceId(), record.getProcessInstanceId())
            ).findAny().orElse(null);

            if (processInstanceRecord != null)
            {
                record.setProcessName(processInstanceRecord.getName());

                UserDto startUser = startUserList.stream().filter(w -> w.getId()
                        .equals(processInstanceRecord.getUserId())).findAny().orElse(null);

                record.setRootUserId(processInstanceRecord.getUserId());
                record.setGroupName(processInstanceRecord.getGroupName());
                record.setRootUserName(startUser.getName());
                record.setRootUserAvatarUrl(startUser.getAvatarUrl());
                record.setStartTime(processInstanceRecord.getCreateTime());
                record.setStartTimeShow(cc.flyflow.common.utils.DateUtil.dateShow(processInstanceRecord.getCreateTime()));
                record.setProcessInstanceBizCode(processInstanceRecord.getProcessInstanceBizCode());
            }

            //进行中  查询谁在处理
            List<TaskDto> taskDtoList = CoreHttpUtil.queryTaskAssignee(null, record.getProcessInstanceId()).getData();
            if (!taskDtoList.isEmpty())
            {
                //正则处理人
                Set<String> taskAssign = taskDtoList.stream().map(w -> w.getAssign()).collect(Collectors.toSet());
                String taskAssignId = CollUtil.newArrayList(taskAssign).get(0);
                UserDto userDto1 = ApiStrategyFactory.getStrategy().getUser(taskAssignId);
                if (taskAssign.size() == 1)
                {
                    record.setTaskAssignShow(userDto1.getName());
                } else
                {
                    String format = StrUtil.format("{}等{}人", userDto1.getName(), taskAssign.size());
                    record.setTaskAssignShow(format);
                }
            }

            //获取表单模板数据 待办 TODO
            fnBizCode(processList, record);
        }

        log.info("[{}]:{}", "To Do List Query Results", pageResultDto.toString());

        return R.success(pageResultDto);
    }

    /**
     * 查询已办任务
     *
     * @param pageVO
     * @return
     */
    @Override
    public R queryFinishedTaskList(ProcessDataQueryVO pageVO)
    {
        //分页参数
        TaskQueryParamDto taskQueryParamDto = BeanUtil.copyProperties(pageVO, TaskQueryParamDto.class);
        taskQueryParamDto.setAssign(StpUtil.getLoginIdAsString());

        R<PageResultDto<TaskDto>> r = CoreHttpUtil.queryCompletedTask(taskQueryParamDto);

        PageResultDto<TaskDto> pageResultDto = r.getData();
        List<TaskDto> records = pageResultDto.getRecords();
        if (CollUtil.isEmpty(records))
        {
            return R.success(pageResultDto);
        }

        Set<String> processInstanceIdSet =
                records.stream().map(w -> w.getProcessInstanceId()).collect(Collectors.toSet());

        //流程实例记录
        List<ProcessInstanceRecord> processInstanceRecordList =
                processInstanceRecordService.lambdaQuery().in(ProcessInstanceRecord::getProcessInstanceId,
                        processInstanceIdSet).list();

        //发起人
        Set<String> startUserIdSet =
                processInstanceRecordList.stream().map(w -> w.getUserId()).collect(Collectors.toSet());

        List<UserDto> startUserList = new ArrayList<>();
        {
            for (String userIds : startUserIdSet)
            {
                UserDto user = ApiStrategyFactory.getStrategy().getUser(userIds);
                startUserList.add(user);
            }
        }

        //流程配置
        Set<String> flowIdSet = processInstanceRecordList.stream().map(w -> w.getFlowId()).collect(Collectors.toSet());
        List<Process> processList = processService.lambdaQuery().in(Process::getFlowId, flowIdSet).list();

        for (TaskDto record : records)
        {

            ProcessInstanceRecord processInstanceRecord =
                    processInstanceRecordList.stream().filter(w -> StrUtil.equals(w.getProcessInstanceId(),
                            record.getProcessInstanceId())).findAny().orElse(null);

            if (processInstanceRecord != null)
            {
                record.setProcessName(processInstanceRecord.getName());

                UserDto startUser = startUserList.stream().filter(w -> w.getId()
                        .equals(processInstanceRecord.getUserId())).findAny().orElse(null);
                record.setRootUserId(processInstanceRecord.getUserId());
                record.setGroupName(processInstanceRecord.getGroupName());
                record.setRootUserName(startUser.getName());
                record.setRootUserAvatarUrl(startUser.getAvatarUrl());
                record.setStartTime(processInstanceRecord.getCreateTime());
                record.setStartTimeShow(DateUtil.dateShow(processInstanceRecord.getCreateTime()));
                record.setProcessInstanceResult(processInstanceRecord.getResult());
                record.setProcessInstanceBizCode(processInstanceRecord.getProcessInstanceBizCode());

                if (processInstanceRecord.getStatus() == ProcessInstanceRecordStatusEnum.JXZ.getCode())
                {
                    //进行中  查询谁在处理
                    List<TaskDto> taskDtoList =
                            CoreHttpUtil.queryTaskAssignee(null, record.getProcessInstanceId()).getData();
                    if (!taskDtoList.isEmpty())
                    {
                        //正则处理人
                        Set<String> taskAssign =
                                taskDtoList.stream().map(w -> w.getAssign()).collect(Collectors.toSet());
                        String taskAssignId = CollUtil.newArrayList(taskAssign).get(0);
                        UserDto userDto1 = ApiStrategyFactory.getStrategy().getUser(taskAssignId);
                        if (taskAssign.size() == 1)
                        {
                            record.setTaskAssignShow(userDto1.getName());
                        } else
                        {
                            String format = StrUtil.format("{}等{}人", userDto1.getName(), taskAssign.size());
                            record.setTaskAssignShow(format);
                        }
                    }
                }

                Process process =
                        processList.stream().filter(w -> StrUtil.equals(w.getFlowId(), record.getFlowId())).findFirst().get();
                List<ProcessInstanceCopy> list =
                        processInstanceCopyMapper.selectList(new LambdaQueryWrapper<ProcessInstanceCopy>()
                                .eq(ProcessInstanceCopy::getProcessInstanceId, record.getProcessInstanceId()));
                if (!list.isEmpty())
                {
                    //获取表单模板数据 已办 TODO
                    record.setProcessInstanceBizCode(fnBizCode(process,
                            JSONObject.parseObject(list.get(0).getFormData() + "")));
                }
            }
        }

        return R.success(pageResultDto);
    }

    /**
     * 逻辑 填充业务编码
     *
     * @param processList 流程信息
     * @param record      实例信息
     */
    public void fnBizCode(List<Process> processList, TaskDto record)
    {
        //表单参数
        Map<String, Object> paramMap = record.getParamMap();

        //处理表单数据
        Process process = processList.stream().filter(w -> StrUtil.equals(w.getFlowId(), record.getFlowId()))
                .findAny().orElse(null);

        List<Dict> formValueShowList = getFormValueShowList(process, record.getFlowId(), record.getNodeId(), paramMap);

        record.setFormValueShowList(formValueShowList);

        //获取表单模板数据 TODO
        JSONArray formItems = JSONObject.parseArray(process.getFormItems());
        for (Object formItem : formItems)
        {
            JSONObject item = JSONObject.parseObject(formItem.toString());
            if (item.containsKey("isShow") && item.getBoolean("isShow"))
            {
                record.setBizCode(paramMap.get(item.getString("id")) + "");
                record.setProcessInstanceBizCode(paramMap.get(item.getString("id")) + "");
            }
        }
    }

    /**
     * 逻辑 填充业务编码
     *
     * @param process  流程模版
     * @param paramMap 流程参数
     */
    public String fnBizCode(Process process, Map<String, Object> paramMap)
    {
        //获取表单模板数据 TODO
        JSONArray formItems = JSONObject.parseArray(process.getFormItems());
        for (Object formItem : formItems)
        {
            JSONObject item = JSONObject.parseObject(formItem.toString());
            if (item.containsKey("isShow") && item.getBoolean("isShow"))
            {
                return paramMap.get(item.getString("id")) + "";
            }
        }
        return "";
    }

    /**
     * 查询我发起的
     *
     * @param pageDto
     * @return
     */
    @Override
    public R queryInitiatedTaskList(ProcessDataQueryVO pageDto)
    {
        String userId = StpUtil.getLoginIdAsString();

        //查询所有的流程id
        List<String> allFlowIdList = new ArrayList<>();
        if (CollUtil.isNotEmpty(pageDto.getFlowIdList()))
        {
            List<String> data = processService.getAllRelatedFlowId(pageDto.getFlowIdList()).getData();
            allFlowIdList.addAll(data);
        }

        Page<ProcessInstanceRecord> instanceRecordPage = processInstanceRecordService.lambdaQuery()
                .eq(ProcessInstanceRecord::getUserId, userId)
                .eq(ProcessInstanceRecord::getTenantId, TenantUtil.get())
                .in(CollUtil.isNotEmpty(allFlowIdList), ProcessInstanceRecord::getFlowId,
                        allFlowIdList)
                .orderByDesc(ProcessInstanceRecord::getCreateTime)
                .page(new Page<>(pageDto.getPageNum(), pageDto.getPageSize()));

        List<ProcessInstanceRecord> records = instanceRecordPage.getRecords();
        if (CollUtil.isEmpty(records))
        {
            return R.success(instanceRecordPage);
        }

        //流程配置
        Set<String> flowIdSet = records.stream().map(w -> w.getFlowId()).collect(Collectors.toSet());
        List<Process> processList = processService.lambdaQuery()
                .in(Process::getFlowId, flowIdSet)
                .eq(Process::getTenantId, TenantUtil.get())
                .list();

        List<ProcessInstanceRecordVO> processInstanceRecordVOList = BeanUtil.copyToList(records,
                ProcessInstanceRecordVO.class);

        UserDto userDto = ApiStrategyFactory.getStrategy().getUser(userId);

        for (ProcessInstanceRecordVO record : processInstanceRecordVOList)
        {
            //处理表单数据
            Process process =
                    processList.stream().filter(w -> StrUtil.equals(w.getFlowId(), record.getFlowId())).findFirst().get();

//            record.setFormData(null);
//            record.setProcess(null);
            record.setStartTimeShow(cc.flyflow.common.utils.DateUtil.dateShow(record.getCreateTime()));
            record.setRootUserAvatarUrl(userDto.getAvatarUrl());
            record.setRootUserName(userDto.getName());
            record.setCancelEnable(false);
            record.setFlowUniqueId(process.getUniqueId());

            //查询流程变量
            Map<String, Object> paramMap =
                    CoreHttpUtil.queryExecutionVariables(record.getProcessInstanceId()).getData();
            List<Dict> formValueShowList = getFormValueShowList(process, record.getFlowId(),
                    ProcessInstanceConstant.VariableKey.START_NODE,
                    paramMap);
            record.setFormValueShowList(formValueShowList);

            if (record.getStatus() == ProcessInstanceRecordStatusEnum.JXZ.getCode())
            {

                //进行中  查询谁在处理
                List<TaskDto> taskDtoList =
                        CoreHttpUtil.queryTaskAssignee(null, record.getProcessInstanceId()).getData();
                if (!taskDtoList.isEmpty())
                {
                    //正则处理人
                    Set<String> taskAssign = taskDtoList.stream().map(w -> w.getAssign()).collect(Collectors.toSet());
                    String taskAssignId = CollUtil.newArrayList(taskAssign).get(0);
                    UserDto userDto1 = ApiStrategyFactory.getStrategy().getUser(taskAssignId);
                    if (taskAssign.size() == 1)
                    {
                        record.setTaskAssignShow(userDto1.getName());
                    } else
                    {
                        String format = StrUtil.format("{}等{}人", userDto1.getName(), taskAssign.size());
                        record.setTaskAssignShow(format);
                    }
                }
            }

            //获取表单模板数据 TODO
            record.setProcessInstanceBizCode(fnBizCode(process, JSONObject.parseObject(record.getFormData())));
        }

        Page page = BeanUtil.copyProperties(instanceRecordPage, Page.class);
        page.setRecords(processInstanceRecordVOList);

        return R.success(page);
    }

    /**
     * 查询抄送给我的
     *
     * @param pageDto
     * @return
     */
    @Override
    public R queryCopiedTaskList(ProcessDataQueryVO pageDto)
    {
        String userId = StpUtil.getLoginIdAsString();

        Page<ProcessInstanceCopy> page = processCopyService.lambdaQuery()
                .eq(ProcessInstanceCopy::getUserId, userId)
                .eq(ProcessInstanceCopy::getTenantId, TenantUtil.get())
                .in(CollUtil.isNotEmpty(pageDto.getFlowIdList()), ProcessInstanceCopy::getFlowId,
                        pageDto.getFlowIdList())
                .orderByDesc(ProcessInstanceCopy::getNodeTime)
                .page(new Page<>(pageDto.getPageNum(), pageDto.getPageSize()));

        List<ProcessInstanceCopy> records = page.getRecords();

        List<ProcessInstanceCopyVo> processCopyVoList = BeanUtil.copyToList(records, ProcessInstanceCopyVo.class);

        if (CollUtil.isNotEmpty(records))
        {
            //发起人
            Set<String> startUserIdSet = records.stream().map(w -> w.getStartUserId()).collect(Collectors.toSet());

            List<UserDto> startUserList = new ArrayList<>();
            for (String s : startUserIdSet)
            {
                UserDto user = ApiStrategyFactory.getStrategy().getUser(s);
                startUserList.add(user);
            }
            Set<String> processInstanceIdSet =
                    records.stream().map(w -> w.getProcessInstanceId()).collect(Collectors.toSet());

            //流程实例记录
            List<ProcessInstanceRecord> processInstanceRecordList = processInstanceRecordService.lambdaQuery()
                    .in(ProcessInstanceRecord::getProcessInstanceId, processInstanceIdSet)
                    .eq(ProcessInstanceRecord::getTenantId, TenantUtil.get())
                    .list();

            //流程配置
            Set<String> flowIdSet =
                    processInstanceRecordList.stream().map(w -> w.getFlowId()).collect(Collectors.toSet());
            List<Process> processList = processService.lambdaQuery()
                    .in(Process::getFlowId, flowIdSet)
                    .eq(Process::getTenantId, TenantUtil.get())
                    .list();

            for (ProcessInstanceCopyVo record : processCopyVoList)
            {
                ProcessInstanceRecord processInstanceRecord =
                        processInstanceRecordList.stream().filter(w -> StrUtil.equals(w.getProcessInstanceId(),
                                record.getProcessInstanceId())).findFirst().get();

                UserDto startUser = startUserList.stream().filter(w -> w.getId()
                        .equals(record.getStartUserId())).findAny().orElse(null);
                record.setStartUserName(startUser.getName());
                record.setStartUserAvatarUrl(startUser.getAvatarUrl());

                //表单参数
                Map<String, Object> paramMap = JSONObject.parseObject(record.getFormData());
                Process process =
                        processList.stream().filter(w -> StrUtil.equals(w.getFlowId(), record.getFlowId())).findFirst().get();

                List<Dict> formValueShowList = getFormValueShowList(process, record.getFlowId(),
                        ProcessInstanceConstant.VariableKey.START_NODE, JsonUtil.parseObject(record.getFormData(),
                                new JsonUtil.TypeReference<Map<String, Object>>()
                                {
                                }));

                record.setFormValueShowList(formValueShowList);
                record.setStartTimeShow(cc.flyflow.common.utils.DateUtil.dateShow(processInstanceRecord.getCreateTime()));
                record.setProcessInstanceResult(processInstanceRecord.getResult());
                record.setProcessInstanceBizCode(processInstanceRecord.getProcessInstanceBizCode());

                if (processInstanceRecord.getStatus() == ProcessInstanceRecordStatusEnum.JXZ.getCode())
                {
                    //进行中  查询谁在处理
                    List<TaskDto> taskDtoList =
                            CoreHttpUtil.queryTaskAssignee(null, record.getProcessInstanceId()).getData();
                    if (!taskDtoList.isEmpty())
                    {
                        //正则处理人
                        Set<String> taskAssign =
                                taskDtoList.stream().map(w -> w.getAssign()).collect(Collectors.toSet());
                        String taskAssignId = CollUtil.newArrayList(taskAssign).get(0);
                        UserDto userDto1 = ApiStrategyFactory.getStrategy().getUser(taskAssignId);
                        if (taskAssign.size() == 1)
                        {
                            record.setTaskAssignShow(userDto1.getName());
                        } else
                        {
                            String format = StrUtil.format("{}等{}人", userDto1.getName(), taskAssign.size());
                            record.setTaskAssignShow(format);
                        }
                    }
                }

                //获取表单模板数据 TODO
                record.setProcessInstanceBizCode(fnBizCode(process, paramMap));
            }
        }

        Page p = BeanUtil.copyProperties(page, Page.class);
        p.setRecords(processCopyVoList);


        return R.success(p);
    }

    /**
     * 获取列表 显示的表单数据 姓名：张三 格式
     *
     * @param process  流程对象
     * @param flowId   流程主键
     * @param nodeId   节点主键
     * @param paramMap 流程实例参数集
     * @return
     */
    private List<Dict> getFormValueShowList(Process process, String flowId, String nodeId, Map<String, Object> paramMap)
    {
        //流程模板数据
        String formItems = process.getFormItems();
        List<FormItemVO> formItemVOList = JsonUtil.parseArray(formItems, FormItemVO.class);

        //声明表单只读数据
        Map<String, String> formPermMap = new HashMap<>();

        //节点不为空逻辑
        if (StrUtil.isNotBlank(nodeId))
        {
            //无效逻辑，计算数据未被使用 TODO
            Node node = processNodeDataService.getNode(flowId, nodeId).getData();
            SuperUserRootNode superUserRootNode = (SuperUserRootNode) node;
            Map<String, String> map = superUserRootNode.getFormPerms();
            log.info("[{}]:{}", logCurrentMethodName(), map.toString());
        } else
        {
            //构建只读数据
            for (FormItemVO formItemVO : formItemVOList)
            {
                formPermMap.put(formItemVO.getId(), ProcessInstanceConstant.FormPermClass.READ);
            }
        }

        List<Dict> formValueShowList = new ArrayList<>();
        buildFormValueShow(paramMap, formItemVOList, formPermMap, formValueShowList);

        List<Dict> list = formValueShowList.size() > 3 ? (formValueShowList.subList(0, 3)) : formValueShowList;
        return list;
    }

    /**
     * 构建表单值显示
     *
     * @param paramMap          表单参数
     * @param formItemVOList    表单模板参数
     * @param formPermMap       表单只读数据
     * @param formValueShowList 表单显示数据
     */
    private static void buildFormValueShow(Map<String, Object> paramMap, List<FormItemVO> formItemVOList,
                                           Map<String, String> formPermMap, List<Dict> formValueShowList)
    {
        for (FormItemVO formItemVO : formItemVOList)
        {
            String id = formItemVO.getId();
            String formItemVOName = formItemVO.getName();

            //计算隐藏数据
            String perm = formPermMap.get(id);
            if (StrUtil.isBlank(perm) || ProcessInstanceConstant.FormPermClass.HIDE.equals(perm))
            {
                continue;
            }

            Object o = paramMap.get(id);
            if (o == null || StrUtil.isBlankIfStr(o))
            {
                formValueShowList.add(Dict.create().set("key", formItemVOName).set("label", ""));
                continue;
            }

            //表单类型
            String type = formItemVO.getType();
            if (o == null || StrUtil.isBlankIfStr(o))
            {
                formValueShowList.add(Dict.create().set("key", formItemVOName).set("label", ""));
                return;
            }
        }
    }

}
